Working with FlexGrid > Grouping > Grouping Data (using ICollectionView) |
The ICollectionView interface includes support for grouping, which allows you to create hierarchical views of your data. For example, to group the customers in the sample above by country and city you would simply change the code from the Populating the grid topic to this:
C# |
Copy Code
|
---|---|
List<Customer> list = GetCustomerList(); PagedCollectionView view = new PagedCollectionView(list); using (view.DeferRefresh()) { view.GroupDescriptions.Clear(); view.GroupDescriptions.Add(new PropertyGroupDescription("Country")); view.GroupDescriptions.Add(new PropertyGroupDescription("Active")); } _flexGrid.ItemsSource = view; |
The statement using (view.DeferRefresh())
is optional. It improves performance by suspending notifications from the data source until all of the groups are set up.
The image below shows the result:
The data items are grouped by country and by their active state. Users can click the icons on group headers to collapse or expand the groups, as they would do with a TreeView control.
If you want to disable grouping at the grid level, set the grid's GroupRowPosition property to GroupRowPosition.None (other options are AboveData and BelowData).
The grouping mechanism offered by the ICollectionView class is simple yet powerful. Each level of grouping is defined by a PropertyGroupDescription object. This object allows you to select the property to use for grouping and also a ValueConverter that determines how to use the property value when grouping.
For example, if we want to group by country initials instead of by country, we modify the code above as follows:
C# |
Copy Code
|
---|---|
List<Customer> list = GetCustomerList(); PagedCollectionView view = new PagedCollectionView(list); using (view.DeferRefresh()) { view.GroupDescriptions.Clear(); view.GroupDescriptions.Add(new PropertyGroupDescription("Country")); view.GroupDescriptions.Add(new PropertyGroupDescription("Active")); var gd = view.GroupDescriptions[0] as PropertyGroupDescription; gd.Converter = new CountryInitialConverter(); } _flexGrid.ItemsSource = view; |
The CountryInitialConverter class implements the IValueConverter interface. It returns the first letter of the country name, using the letter for grouping instead of the full country name:
C# |
Copy Code
|
---|---|
// converter used to group countries by their first initial class CountryInitialConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return ((string)value)[0].ToString().ToUpper(); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } |
After making this small change, customers are grouped by their country's first letter instead of by the full country name:
Notice that the group rows display information about the groups they represent (the property and value being grouped on, and the item count).
To customize that information, create a new IValueConverter class and assign it to the grid's GroupHeaderConverter property.
For example, the default group header converter (the one that shows the information in the image) is implemented as follows:
C# |
Copy Code
|
---|---|
// class used to format group captions for display public class GroupHeaderConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var gr = parameter as GroupRow; var group = gr.Group; if (group != null && gr != null && targetType == typeof(string)) { var desc = gr.Grid.View.GroupDescriptions[gr.Level] as PropertyGroupDescription; return desc != null ? string.Format("{0}: {1} ({2:n0} items)", desc.PropertyName, group.Name, group.ItemCount) : string.Format("{0} ({1:n0} items)", group.Name, group.ItemCount); } return value; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value; } } |